import { Recordable } from '@/global'
import type { PropType, VNode } from 'vue'
import _Button from 'element-plus/lib/el-button/index'
import { RuleItem } from 'async-validator'
import { ColEx, ComponentType } from '.'

export type RegisterFn = (formInstance: FormActionType) => void

export type UseFormReturnType = [RegisterFn, FormActionType]
export interface RenderCallbackParams {
  schema: FormSchema
  values: Recordable
  model: Recordable
  field: string
}

export interface FormProps {
  // 表单数据对象
  model?: Recordable
  // 表单验证规则
  rules?: Recordable
  // 表单域标签的宽度
  labelWidth?: string
  // 是否在输入框中显示校验结果反馈图标
  statusIcon?: boolean
  // 用于控制该表单内组件的尺寸
  size?: 'medium' | 'small' | 'mini'
  // 是否禁用该表单内的所有组件
  disabled?: boolean
  // 配置表单
  schemas?: FormSchema[]
  baseColProps?: Partial<ColEx>
  showAdvancedButton?: boolean
  resetButtonOptions?: Partial<typeof _Button>
  submitButtonOptions?: Partial<typeof _Button>
  actionColOptions?: Partial<ColEx>
  showResetButton?: boolean
  showSubmitButton?: boolean
}

export interface FormSchema {
  // 字段名/属性名
  field: string
  changeEvent?: string
  // 标签文本
  label: string
  // 表单域 model 字段
  prop?: string
  // 单个校验
  rules?: PropType<RuleItem | RuleItem[]>
  // 是否必填
  required?: boolean
  // 辅助文本
  subLabel?: string
  // 表单域标签的的宽度
  labelWidth?: string
  // 以行内形式展示校验信息
  inlineMessage?: boolean
  // 渲染组件
  component: ComponentType
  // 组件属性
  componentProps?:
    | ((opt: {
        schema: FormSchema
        formActionType: FormActionType
        formModel: Recordable
      }) => Recordable)
    | object

  // 默认值
  defaultValue?: any
  // 是否显示。相当于v-if
  ifShow?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean)
  // 是否显示。相当于v-show
  show?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean)
  // 自定义插槽
  slot?: string
  // 渲染函数
  render?: (renderCallbackParams: RenderCallbackParams) => VNode | VNode[] | string
  suffix?: string | number | ((values: RenderCallbackParams) => string | number)
  colProps?: Partial<ColEx>
  // 关联是否disabled
  dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams) => boolean)
  // 关联Rules
  dynamicRules?: (renderCallbackParams: RenderCallbackParams) => PropType<RuleItem | RuleItem[]>
  isAdvanced?: boolean
}

export interface FormActionType {
  // 提交
  submit: () => Promise<void>
  // 表单赋值
  setFieldsValue: <T>(values: T) => Promise<void>
  // 重置表单
  resetFields: () => Promise<void>
  // 获取表单值
  getFieldsValue: () => Recordable
  clearValidate: (name?: string | string[]) => Promise<void>
  validate: () => Promise<any>
  setProps: (formProps: Partial<FormProps>) => Promise<void>
}
